define(["../../Core/Cartesian3",
    "../../Core/Color",
    "../../Core/defineProperties",
    "../../Core/PolygonGeometry",
    "../../Core/PolygonHierarchy",
    "../../DataSources/CallbackProperty",
    "../../Renderer/Pass",
    "../../Renderer/RenderState",
    "../../Scene/BlendingState",
    "../../Scene/BlendOption",
    "../../Scene/HorizontalOrigin",
    "../../Scene/LabelCollection",
    "../../Scene/LabelStyle",
    "../../Scene/PointPrimitiveCollection",
    "../../Scene/VerticalOrigin",
    "./support/MeasureUnit",
    "./support/EventDriven",
    "./support/PickGlobe",
    '../../Core/ScreenSpaceEventHandler',
    '../../Core/ScreenSpaceEventType',
    '../../Scene/Primitive',
    '../../Core/GeometryInstance',
    '../../Core/ColorGeometryInstanceAttribute',
    '../../Scene/PerInstanceColorAppearance',
    '../../Scene/ClassificationType',
    "../../Core/Ellipsoid",
    "../../Core/Math",
    "../../Core/Cartesian2",
    "../../Core/defined",
    "../../Scene/EllipsoidSurfaceAppearance",
    "../../Scene/Material"
], function(
    Cartesian3,
    Color,
    defineProperties,
    PolygonGeometry,
    PolygonHierarchy,
    CallbackProperty,
    Pass,
    RenderState,
    BlendingState,
    BlendOption,
    HorizontalOrigin,
    LabelCollection,
    LabelStyle,
    PointPrimitiveCollection,
    VerticalOrigin,
    AreaUnit,
    EventDriven,
    PickGlobe,
    ScreenSpaceEventHandler,
    ScreenSpaceEventType,

    Primitive,
    GeometryInstance,
    ColorGeometryInstanceAttribute,
    PerInstanceColorAppearance,
    ClassificationType,
    Ellipsoid,
    CMath,
    Cartesian2,
    defined,
    EllipsoidSurfaceAppearance,
    Material
) {
    "use strict";
    function MeasureArea(viewer) {
        this.viewer = viewer;
        this.scene = viewer.scene;
        this._enable = false;
        this.startDraw = false;
        this._bAddTemp = true;
        this.leftpoints = [];
        this.poinsTemp = [];
        this.pointsCompare = [];
        this.pixelPoints = [];
        this._area = 0;
        this.elementEvent = undefined;

        this.polygonEntity = null

        this._measureUnit = AreaUnit.SQUAREMETER;
        this._pointCollection = new PointPrimitiveCollection({
            blendOption: BlendOption.TRANSLUCENT
        });
        this._labelCollection = new LabelCollection({
            blendOption: BlendOption.TRANSLUCENT,
            depthMask: false
        });
        this.areaLabel = this._labelCollection.add({
            show: true,
            showBackground: true,
            font: "36px KaiTi",
            fillColor: Color.WHITE,
            outlineColor: Color.BACK,
            outlineWidth: 5,
            style: LabelStyle.FILL_AND_OUTLINE,
            horizontalOrigin: HorizontalOrigin.CENTER,
            verticalOrigin: VerticalOrigin.BASELINE,
            disableDepthTestDistance: 1e4,
            scale: .5
        });
        this.endPixelPoint = this._pointCollection.add({
            name: "",
            position: Cartesian3.ZERO,
            pixelSize: 5,
            color: Color.RED,
            disableDepthTestDistance: 1e4
        });
        var self = this;

        this.lineTemp = viewer.entities.add({
            name: "",
            polyline: {
                positions: new CallbackProperty(function() {
                        if (!(self.poinsTemp.length < 2))
                            return self.poinsTemp
                    }
                    ,false),
                width: 5,
                material: new Color(.5,1,1,.7)
            }
        }),
            this.scene.primitives.add(this)

        this.pickGlobe = new PickGlobe(this.viewer);

        this.clickDraw = new ScreenSpaceEventHandler(this.scene.canvas);
        this.clickDraw.setInputAction(function(movement) {
            self._enable = true;
            if(self._pointCollection.length > 1){
                var obj = document.getElementById('mybutton');
                obj && self.viewer.scene.postRender.removeEventListener(self.elementEvent);
                obj && document.body.removeChild(obj)
            }
            self.addPoint3D(movement)
            createElements(movement, self)
        },ScreenSpaceEventType.LEFT_CLICK)

        // this.moveDraw = new ScreenSpaceEventHandler(this.scene.canvas);
        // this.moveDraw.setInputAction(function(movement) {
        // self.addPointTemp(movement)
        // },ScreenSpaceEventType.MOUSE_MOVE)

        // this.stopDraw = new ScreenSpaceEventHandler(this.scene.canvas);
        // this.stopDraw.setInputAction(function(movement) {
        //    self.clickDraw && !self.clickDraw.isDestroyed() && self.clickDraw.destroy();
        //     self.moveDraw && !self.moveDraw.isDestroyed() && self.moveDraw.destroy();
        //     self.finish()
        // },ScreenSpaceEventType.RIGHT_CLICK)

    }

    //创建元素
    function createElements(movement, self){
        var ray = self.viewer.scene.camera.getPickRay(movement.position)
        var cartesian = self.viewer.scene.globe.pick(ray, self.viewer.scene)
        var position1 = Ellipsoid.WGS84.cartesianToCartographic(cartesian)
        var myElement=document.createElement("input");
        myElement.type="button";
        //给新元素添加必要的信息
        myElement.id="mybutton";
        myElement.value="确定";
        //给新元素指定位置
        myElement.style.position="absolute";
        //添加到document.body上
        document.body.appendChild(myElement);
        myElement.onclick = function() {
            self.clickDraw && !self.clickDraw.isDestroyed() && self.clickDraw.destroy();
            self.moveDraw && !self.moveDraw.isDestroyed() && self.moveDraw.destroy();
            self.finish()
            self.viewer.scene.postRender.removeEventListener(self.elementEvent);
            document.body.removeChild(myElement);
        };
        self.elementEvent = function() {
            var position = Cartesian3.fromDegrees(CMath.toDegrees(position1.longitude),CMath.toDegrees(position1.latitude), position1.height);
            var scratch = new Cartesian2();
            var canvasPosition = self.viewer.scene.cartesianToCanvasCoordinates(position, scratch);
            if (defined(canvasPosition)) {
                myElement.style.top = (canvasPosition.y + 10) + 'px';
                myElement.style.left = (canvasPosition.x + 10) + 'px';
            }
        }
        // 定义元素位置
        self.viewer.scene.postRender.addEventListener(self.elementEvent);
    }

    function g(t) {

        var n = new PolygonGeometry({
            polygonHierarchy: new PolygonHierarchy(t.leftpoints),
            vertexFormat : EllipsoidSurfaceAppearance.VERTEX_FORMAT,
        })
            , o = PolygonGeometry.createGeometry(n);

        t.polygonEntity && t.viewer.entities.remove(t.polygonEntity)
        // var groundPolygon = new Primitive({
        //     geometryInstances: new GeometryInstance({
        //         geometry: n,
        //         id: 'meaturepolygon123'
        //     }),
        //     appearance : new EllipsoidSurfaceAppearance({
        //         aboveGround : false,
        //         material: new Material({
        //             fabric : {
        //                 type : 'Color',
        //                 uniforms : {
        //                     color : Color.CYAN.withAlpha(0.3)
        //                 }
        //             }
        //         })
        //     })
        // });
        t.polygonEntity = t.viewer.entities.add({
            name : 'Red polygon on surface',
            polygon : {
                hierarchy : t.leftpoints,
                material :  Color.CYAN.withAlpha(0.3),
                height: 2
            }
        })  //t.scene.primitives.add(groundPolygon)

        if (void 0 != o) {
            for (var a = o.indices, s = o.attributes.position.values, l = [], u = 0, c = 0; c < s.length / 3; c++) {
                var d = new Cartesian3(0,0,0);
                d.x = s[3 * c],
                    d.y = s[3 * c + 1],
                    d.z = s[3 * c + 2],
                    l.push(d)
            }
            for (var c = 0; c < a.length / 3; c++) {
                var h = [];
                h.push(l[a[3 * c]], l[a[3 * c + 1]], l[a[3 * c + 2]]);
                var _ = Cartesian3.distance(h[0], h[1])
                    , p = Cartesian3.distance(h[0], h[2])
                    , m = Cartesian3.distance(h[1], h[2])
                    , f = (_ + p + m) / 2;
                u += Math.sqrt(f * (f - _) * (f - m) * (f - p))
            }
            for (var g = 0, v = 0, y = 0, c = 0; c < t.leftpoints.length; c++)
                g += t.leftpoints[c].x,
                    v += t.leftpoints[c].y,
                    y += t.leftpoints[c].z;
            var S = new Cartesian3(0,0,0);
            S.x = g / t.leftpoints.length,
                S.y = v / t.leftpoints.length,
                S.z = y / t.leftpoints.length,
                t.polygonEntity.show = true,
                t._area = u.toFixed(2),
                t.areaLabel.position = S,
                t.areaLabel.show = true,
                0 == t._measureUnit ? t.areaLabel.text = "面积:" + u.toFixed(2) + "平方米" : 1 == t._measureUnit && (t.areaLabel.text = "面积:" + (u / 1e6).toFixed(2) + "平方千米")
        }
    }
    defineProperties(MeasureArea.prototype, {
        enable: {
            get: function() {
                return this._enable
            },
            set: function(e) {
                this._enable !== e && (this._enable = e)
            }
        },
        area: {
            get: function() {
                return this._area
            }
        },
        unit: {
            get: function() {
                return this._measureUnit
            },
            set: function(e) {
                switch (e) {
                    case 0:
                        this._measureUnit = AreaUnit.SQUAREMETER;
                        break;
                    case 1:
                        this._measureUnit = AreaUnit.SQUAREKILOMETER;
                        break;
                    default:
                        this._measureUnit = AreaUnit.SQUAREMETER
                }
            }
        }
    });
    MeasureArea.prototype.addPoint3D = function(e) {
        if (this._enable) {
            var n = this.pickGlobe.pickGlobe(e.position);
            if (this.startDraw && void 0 == n && this.leftpoints.length > 0 && (n = this.leftpoints[this.leftpoints.length - 1].clone(),
                0 == this.pointsCompare.length && this.pointsCompare.push(n),
                1 == this.pointsCompare.length && (this.pointsCompare.pop(),
                    this.pointsCompare.push(n))),
                void 0 != n) {
                this.startDraw || (this.pointsTemp = [],
                    this.lineTemp.show = true,
                    this.endPixelPoint.show = true,
                    this.endPixelPoint.position = n)
                this.startDraw = true;
                this._bAddTemp = true;
                var i = this._pointCollection.add({
                    name: "",
                    position: n,
                    pixelSize: 5,
                    color: new Color(1,1,1,0.01), //new Color(1,1,1,0.01),
                    disableDepthTestDistance: 1e4
                });
                this.pixelPoints.push(i)
                this.leftpoints.push(n)
                2 >= this.poinsTemp.length && (this.poinsTemp.push(n))
            }
            this.leftpoints.length > 2 && (this.lineTemp.show = false,
                g(this))
        }
    };
    MeasureArea.prototype.addPointTemp = function(e) {
        if (this._enable && this.startDraw) {
            var t = this.pickGlobe.pickGlobe(e.endPosition||e.position);
            void 0 != t && (this._bAddTemp && (this.leftpoints.push(t),
                this._bAddTemp = false),
                1 == this.poinsTemp.length ? this.poinsTemp.push(t) : 2 == this.poinsTemp.length && (this.poinsTemp[1] = t),
            void 0 != t && this.startDraw && (this.endPixelPoint.position = this.leftpoints[this.leftpoints.length - 1] = t,
            this.leftpoints.length > 2 && g(this)))
        }
    };
    MeasureArea.prototype.finish = function() {
        this.leftpoints.length < 3 && this.clear(),
        void 0 !== this.pointsCompare[0] && void 0 !== this.leftpoints[this.leftpoints.length - 1] && (this.pointsCompare[0].x == this.leftpoints[this.leftpoints.length - 1].x && this.pointsCompare[0].y == this.leftpoints[this.leftpoints.length - 1].y && this.pointsCompare[0].z == this.leftpoints[this.leftpoints.length - 1].z || this.leftpoints.pop()),
            this._enable = false,
            this.startDraw = false,
            this._bAddTemp = true,
            this.endPixelPoint.show = false
    };
    MeasureArea.prototype.clear = function() {
        this.leftpoints = [];
        this.poinsTemp = [];
        this.polygonEntity && (this.polygonEntity.show = false);
        this.areaLabel.show = false;
        this._enable = false;
        this.startDraw = false;
        this._bAddTemp = true;
        for (var e = 0; e < this.pixelPoints.length; e++) {
            var t = this.pixelPoints[e];
            void 0 != t && this._pointCollection.remove(t)
        }
        this.pixelPoints = [];
        this.endPixelPoint.show = false;
        var J = document.getElementById("mybutton");
        this.elementEvent && this.viewer.scene.postRender.removeEventListener(this.elementEvent);
        J && document.body.removeChild(J);
    };
    MeasureArea.prototype.update = function(e) {
        this._pointCollection.update(e);
        var t = e.commandList.length;
        this._labelCollection.update(e);
        for (var n = e.commandList.length; t < n; ++t)
            e.commandList[t].pass = Pass.OVERLAY,
                e.commandList[t].renderState = RenderState.fromCache({
                    depthTest: {
                        enabled: false
                    },
                    depthMask: false,
                    blending: BlendingState.ALPHA_BLEND
                })
    };
    MeasureArea.prototype._destroy = function() {
        this._pointCollection = this._pointCollection.destroy();
        this._labelCollection = this._labelCollection.destroy();
    }
    return MeasureArea;
})